#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ETH Ticker订阅脚本

功能：
1. 订阅ETH-USDT的ticker行情数据
2. 实时显示价格、买一价、卖一价、24小时涨跌幅等信息
3. 可选择保存数据到CSV文件
"""

import os
import sys
import time
import json
import logging
import argparse
import asyncio
import pandas as pd
from datetime import datetime
from pathlib import Path

# 添加项目根目录到Python路径
project_root = Path(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(str(project_root))

from services.exchange.adapters.gate_adapter import GateAdapter
from utils.logger import setup_logger

# 创建日志记录器
logger = setup_logger("eth_ticker", level=logging.INFO)

class ETHTickerMonitor:
    """ETH Ticker监控类"""
    
    def __init__(self, symbol="ETH-USDT", use_testnet=False, save_data=False):
        """
        初始化ETH Ticker监控器
        
        参数:
            symbol: 交易对符号，默认为ETH-USDT
            use_testnet: 是否使用测试网络
            save_data: 是否保存数据到CSV文件
        """
        self.symbol = symbol
        self.use_testnet = use_testnet
        self.save_data = save_data
        self.exchange = GateAdapter(use_testnet=use_testnet)
        self.ticker_data = []
        
        # 如果需要保存数据，创建数据目录
        if save_data:
            self.data_dir = project_root / "data" / "ticker"
            self.data_dir.mkdir(parents=True, exist_ok=True)
            self.data_file = self.data_dir / f"{symbol.replace('-', '_')}_{datetime.now().strftime('%Y%m%d')}.csv"
            logger.info(f"Ticker数据将保存到: {self.data_file}")
    
    def handle_ticker_update(self, data):
        """
        处理ticker数据更新
        
        参数:
            data: ticker数据列表
        """
        for ticker in data:
            # 检查是否是我们关注的交易对
            contract = ticker.get('contract', '')
            symbol_normalized = self.symbol.replace('-', '_').upper()
            
            if contract != symbol_normalized:
                continue
                
            # 提取关键数据
            timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
            last_price = float(ticker.get('last', 0))
            mark_price = float(ticker.get('mark_price', 0))
            index_price = float(ticker.get('index_price', 0))
            ask1_price = float(ticker.get('ask_price', 0))
            bid1_price = float(ticker.get('bid_price', 0))
            ask1_size = float(ticker.get('ask_size', 0))
            bid1_size = float(ticker.get('bid_size', 0))
            volume_24h = float(ticker.get('volume_24h', 0))
            change_percentage = float(ticker.get('change_percentage', 0))
            
            # 格式化输出
            change_emoji = "🔴" if change_percentage < 0 else "🟢"
            logger.info(f"[{timestamp}] {self.symbol} {change_emoji}")
            logger.info(f"最新价: {last_price:.2f} | 标记价: {mark_price:.2f} | 指数价: {index_price:.2f}")
            logger.info(f"买一价: {bid1_price:.2f} ({bid1_size:.4f}) | 卖一价: {ask1_price:.2f} ({ask1_size:.4f})")
            logger.info(f"24h成交量: {volume_24h:.2f} | 24h涨跌幅: {change_percentage:.2f}%")
            logger.info("-" * 50)
            
            # 保存数据到列表
            ticker_record = {
                'timestamp': timestamp,
                'last_price': last_price,
                'mark_price': mark_price,
                'index_price': index_price,
                'bid_price': bid1_price,
                'ask_price': ask1_price,
                'bid_size': bid1_size,
                'ask_size': ask1_size,
                'volume_24h': volume_24h,
                'change_percentage': change_percentage
            }
            self.ticker_data.append(ticker_record)
            
            # 每100条数据保存一次
            if self.save_data and len(self.ticker_data) >= 100:
                self.save_to_csv()
    
    def save_to_csv(self):
        """保存数据到CSV文件"""
        if not self.ticker_data:
            return
            
        try:
            df = pd.DataFrame(self.ticker_data)
            
            # 如果文件存在，追加数据；否则创建新文件
            if self.data_file.exists():
                df.to_csv(self.data_file, mode='a', header=False, index=False)
            else:
                df.to_csv(self.data_file, mode='w', header=True, index=False)
                
            logger.info(f"保存了 {len(self.ticker_data)} 条ticker数据到 {self.data_file}")
            
            # 清空数据列表
            self.ticker_data = []
        except Exception as e:
            logger.error(f"保存数据到CSV文件时出错: {e}")
    
    async def run(self):
        """运行Ticker监控器"""
        try:
            # 订阅ticker数据
            symbol_display = self.symbol.replace('-', '_').upper()
            network_type = "测试网" if self.use_testnet else "主网"
            logger.info(f"开始订阅 {network_type} {symbol_display} 的ticker数据...")
            
            success = self.exchange.subscribe_ticker(self.symbol, self.handle_ticker_update)
            
            if success:
                logger.info(f"成功订阅 {symbol_display} ticker数据")
                
                # 保持程序运行
                while True:
                    await asyncio.sleep(1)
            else:
                logger.error(f"订阅 {symbol_display} ticker数据失败")
                return
                
        except KeyboardInterrupt:
            logger.info("程序被用户中断")
        except Exception as e:
            logger.error(f"运行时出错: {e}")
        finally:
            # 保存剩余数据
            if self.save_data and self.ticker_data:
                self.save_to_csv()
                
            # 关闭所有连接
            logger.info("关闭WebSocket连接...")
            self.exchange.close_all_ws_connections()
            logger.info("程序退出")


async def main():
    """主函数"""
    parser = argparse.ArgumentParser(description="ETH Ticker数据订阅工具")
    parser.add_argument("--symbol", type=str, default="ETH-USDT", help="交易对符号，默认为ETH-USDT")
    parser.add_argument("--testnet", action="store_true", help="使用测试网络")
    parser.add_argument("--save", action="store_true", help="是否保存数据到CSV文件")
    args = parser.parse_args()
    
    # 创建并运行监控器
    monitor = ETHTickerMonitor(
        symbol=args.symbol,
        use_testnet=args.testnet,
        save_data=args.save
    )
    
    await monitor.run()


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("程序被用户中断")
    except Exception as e:
        print(f"程序运行时出错: {e}") 